
#include "aobjpool.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

int create_aobjs(aobjpool *cache); 

aobjpool *aobjpool_create(int count, int datalen)
{
	int ret = 0;
	aobjpool *cache = (aobjpool*)malloc(sizeof(aobjpool));
	if(!cache) return NULL;

	memset(cache, 0, sizeof(aobjpool));
	cache->count = count;
	cache->datalen = datalen;

	ret = create_aobjs(cache);
	if(ret<0) goto eout;

	return cache;

eout:
	if(cache) free(cache);
	return NULL;	
}

void aobjpool_destory(aobjpool *cache)
{
	if(cache)
	{
		abuf *obuf = cache->bufs;
		while(obuf)
		{
			abuf *tmp = obuf->next;
			free(obuf->buf);
			free(obuf);
			obuf = tmp;
		}

		free(cache);
		cache = NULL;
	}	
}


__inline int create_aobjs(aobjpool *cache)
{
	aobj *obj = NULL;
	abuf *obuf = NULL;
	int i = 0;
	int objsize = sizeof(aobj)+cache->datalen;

	if(!cache) return -1;

	// init buf
	obuf = (abuf*)malloc(sizeof(abuf));
	if(!obuf) return -10;
	obuf->next = NULL;
	obuf->buf = (char*)malloc(cache->count *objsize);
	if(!obuf->buf) 
	{
		free(obuf);
		return -11;
	}

	// set objs list
	memset(obuf->buf, 0, cache->count *objsize);
	obj = (aobj*)(obuf->buf + objsize*i);
	obj->data = obuf->buf + objsize*i + sizeof(aobj);
	if(cache->head)
	{
		obj->next = cache->head;
		cache->head = obj;
	}
	else
	{
		obj->next = NULL;
		cache->head = obj;
	}

	for(i=1; i<cache->count; i++)
	{
		obj = (aobj*)(obuf->buf + objsize*i);
		obj->data = obuf->buf + objsize*i + sizeof(aobj);
		obj->next = cache->head;
		cache->head = obj;
	}

	// save to buf list
	if(cache->bufs)
	{
		obuf->next = cache->bufs;
	}
	cache->bufs = obuf;
	return 0;
}

int aobjpool_put(aobjpool *cache, aobj *obj)
{
	if(!cache) return -1;

	if(cache->head)
	{
		obj->next = cache->head;
	}
	cache->head = obj;

	return 0;	
}

aobj *aobjpool_get(aobjpool *cache)
{
	aobj *obj = NULL;
	if(!cache) return NULL;

	if(!cache->head)
	{
 		int ret =create_aobjs(cache);
		if(ret<0) return NULL;
	}

	obj = cache->head;
	cache->head = obj->next;
	obj->next = NULL;

	return obj;
}




// unit test

void print_pool(aobjpool *cache)
{
	aobj *obj = NULL;
	if(!cache) return;

	obj = cache->head;
	while(obj)
	{
		printf("+%s\n", (char*)obj->data);
		obj = obj->next;
	}
}

void test_aobjpool()
{
	int i = 0;
	int ret = 0;
	char *strs[] = {"1hello","2my","3friends,old friends, new friends, ha ha ha","4hellos","5the","6world"};

	aobj *objs[5];
	aobj *tmp = NULL;
	aobjpool *cache = aobjpool_create(4,20);
	printf("\n=============init 4 objs=============\n");
	print_pool(cache);

	printf("\n=============get 5 times=============\n");
	for(i=0; i<5; i++)
	{
		objs[i] = aobjpool_get(cache);
		if(objs[i])
		{
			strncpy((char*)objs[i]->data, strs[i],19);
		}
	}
	print_pool(cache);
	
	printf("======put 5 times=====\n");
	for(i=0; i<5; i++)
	{
		ret = aobjpool_put(cache, objs[i]);
	}
	print_pool(cache);


	printf("======get 4 times=====\n");
	for(i=0; i<4; i++)
	{
		tmp = aobjpool_get(cache);
		if(tmp)
			printf("aobjpool_get=%s\n", (char*)tmp->data);
	}

	printf("======left=====\n");
	print_pool(cache);

	aobjpool_destory(cache);
	return;
}
